/**
 * @author Jason Pratt
 * @deprecated  now using TabbedEditorComponent
 */

package edu.cmu.cs.stage3.alice.authoringtool;

import edu.cmu.cs.stage3.alice.authoringtool.datatransfer.CallToUserDefinedQuestionPrototypeReferenceTransferable;
import edu.cmu.cs.stage3.alice.authoringtool.datatransfer.CallToUserDefinedResponsePrototypeReferenceTransferable;
import edu.cmu.cs.stage3.alice.authoringtool.datatransfer.ElementReferenceTransferable;
import edu.cmu.cs.stage3.alice.authoringtool.datatransfer.ResponsePrototypeReferenceTransferable;

//Rem @Deprecated
public class EditorComponent extends javax.swing.JPanel {

 protected AuthoringTool authoringTool;
 protected javax.swing.JPanel editorPanel = new javax.swing.JPanel();
 protected EditLabel editLabel = new EditLabel();
 protected javax.swing.AbstractAction backAction;
 protected javax.swing.AbstractAction forwardAction;
 protected javax.swing.AbstractAction editSceneAction;
 protected edu.cmu.cs.stage3.alice.authoringtool.Editor activeEditor = null;
 protected java.lang.reflect.Method activeEditorSetMethod = null;
 protected java.util.HashMap cachedEditors = new java.util.HashMap();
 protected EditStack editStack = new EditStack();

 protected final edu.cmu.cs.stage3.alice.core.event.ChildrenListener deletionListener = new edu.cmu.cs.stage3.alice.core.event.ChildrenListener() {
  public void childrenChanging (edu.cmu.cs.stage3.alice.core.event.ChildrenEvent ev) {}
  public void childrenChanged (edu.cmu.cs.stage3.alice.core.event.ChildrenEvent ev) {
   if ((ev.getChangeType() == edu.cmu.cs.stage3.alice.core.event.ChildrenEvent.CHILD_REMOVED) && (ev.getChild() == EditorComponent.this.getElementBeingEdited())) {
    EditorComponent.this.editElement( null );
    ev.getParent().removeChildrenListener( this );
    }
   }
  };

 public edu.cmu.cs.stage3.alice.authoringtool.Editor loadEditor (Class editorClass) {
  edu.cmu.cs.stage3.alice.authoringtool.Editor editor = null;
  if (editorClass != null) {
   editor = (Editor)cachedEditors.get( editorClass );
   if (editor == null) {
    try {
     editor = edu.cmu.cs.stage3.alice.authoringtool.util.EditorUtilities.getEditorFromClass( editorClass );
     if (editor == null) {
      AuthoringTool.getInstance().showErrorDialog( "Can't create editor of type " + editorClass.getName(), null );
     } else {
      cachedEditors.put( editorClass, editor );
      authoringTool.addAuthoringToolStateListener( editor );
      editor.setAuthoringTool( authoringTool );
      }
    } catch( Throwable t) {
     AuthoringTool.getInstance().showErrorDialog( "Error while creating editor of type " + editorClass.getName(), t );
     }
    }
   }
  return editor;
  }

 public void editElement (edu.cmu.cs.stage3.alice.core.Element element) {
  editElement( element, true );
  }

 protected void editElement (edu.cmu.cs.stage3.alice.core.Element element, boolean performPush) {
  if (element == null) {
   editElement( null, null, performPush );
  } else {
   Class bestEditorClass = edu.cmu.cs.stage3.alice.authoringtool.util.EditorUtilities.getBestEditor( element.getClass() );
   if (bestEditorClass == null) {
    AuthoringTool.getInstance().showErrorDialog( "No editor found for " + element.getClass().getName(), null );
    }
   editElement( element, bestEditorClass, performPush );
   }
  }

 protected void editElement (edu.cmu.cs.stage3.alice.core.Element element, Class editorClass, boolean performPush) {
  if ((getElementBeingEdited() != null) && (getElementBeingEdited().getParent() != null)) {
   getElementBeingEdited().getParent().removeChildrenListener( deletionListener );
   }

  edu.cmu.cs.stage3.alice.authoringtool.Editor editor = loadEditor( editorClass );

  // if we have a new editor...
  if (activeEditor != editor) {
   // clean up old editor if necessary
   if ((activeEditor != null)) {
    try {
     activeEditorSetMethod.invoke( activeEditor, new Object[] { null } );
    } catch( java.lang.reflect.InvocationTargetException ite) {
     AuthoringTool.getInstance().showErrorDialog( "Error while cleaning editor.", ite );
    } catch( IllegalAccessException iae) {
     AuthoringTool.getInstance().showErrorDialog( "Error while cleaning editor.", iae );
     }
    }

   // setup new editor
   editorPanel.removeAll();
   activeEditor = editor;
   if (activeEditor != null) {
    activeEditorSetMethod = edu.cmu.cs.stage3.alice.authoringtool.util.EditorUtilities.getSetMethodFromClass( editorClass );
    editorPanel.add( java.awt.BorderLayout.CENTER, activeEditor.getJComponent() );
   } else {
    activeEditorSetMethod = null;
    }
   editorPanel.revalidate();
   editorPanel.repaint();
   }

  // if the new editor isn't null, start editing the element
  if ((activeEditor != null) && (activeEditor.getObject() != element)) {
   try {
    activeEditorSetMethod.invoke( activeEditor, new Object[] { element } );
    if (performPush && (element != null)) {
     editStack.push( new EditItem( element, editorClass ) );
     updateActions();
     }
    if (element != null) {
     editLabel.setText( AuthoringToolResources.getReprForValue( element ) );
     if (element.getParent() != null) {
      element.getParent().addChildrenListener( deletionListener );
      }
     }
   } catch( java.lang.reflect.InvocationTargetException ite) {
    AuthoringTool.getInstance().showErrorDialog( "Error while setting up editor.", ite );
   } catch( IllegalAccessException iae) {
    AuthoringTool.getInstance().showErrorDialog( "Error while setting up editor.", iae );
    }
   }
  }

 public edu.cmu.cs.stage3.alice.core.Element getElementBeingEdited () {
  if (activeEditor != null) {
   return (edu.cmu.cs.stage3.alice.core.Element)activeEditor.getObject();
  } else {
   return null;
   }
  }

 public edu.cmu.cs.stage3.alice.authoringtool.Editor getActiveEditor () {
  return activeEditor;
  }

 public boolean canGoBack () {
  return editStack.getCurrentUndoableRedoableIndex() > 0;
  }

 public boolean canGoForward () {
  return editStack.getCurrentUndoableRedoableIndex() != (editStack.size() - 1);
  }

 protected void updateActions () {
  backAction.setEnabled( canGoBack() );
  forwardAction.setEnabled( canGoForward() );
  editSceneAction.setEnabled( getElementBeingEdited() != authoringTool.getWorld() );
  }

 class EditStack extends edu.cmu.cs.stage3.alice.authoringtool.util.DefaultUndoRedoStack {
  //Rem @Override
  public edu.cmu.cs.stage3.alice.authoringtool.util.UndoableRedoable undo () {
   edu.cmu.cs.stage3.alice.authoringtool.util.UndoableRedoable ur = super.undo();
   edu.cmu.cs.stage3.alice.authoringtool.util.UndoableRedoable newItem = editStack.getCurrentUndoableRedoable();
   if (ur != null) {
    editElement( ((EditItem)newItem).getElement(), ((EditItem)newItem).getEditorClass(), false );
    }
   return ur;
   }

  //Rem @Override
  public edu.cmu.cs.stage3.alice.authoringtool.util.UndoableRedoable redo () {
   edu.cmu.cs.stage3.alice.authoringtool.util.UndoableRedoable ur = super.redo();
   if (ur != null) {
    editElement( ((EditItem)ur).getElement(), ((EditItem)ur).getEditorClass(), false );
    }
   return ur;
   }
  }

 class EditItem implements edu.cmu.cs.stage3.alice.authoringtool.util.UndoableRedoable {
  protected edu.cmu.cs.stage3.alice.core.Element element;
  protected Class editorClass;

  public EditItem (edu.cmu.cs.stage3.alice.core.Element element, Class editorClass) {
   this.element = element;
   this.editorClass = editorClass;
   }

  public void undo () {}
  public void redo () {}

  public Object getAffectedObject () {
   return element;
   }

  public Object getContext () {
   return EditorComponent.this;
   }

  public edu.cmu.cs.stage3.alice.core.Element getElement () {
   return element;
   }

  public Class getEditorClass () {
   return editorClass;
   }
  }

 public class EditLabel extends javax.swing.JLabel implements java.awt.dnd.DropTargetListener {
  public EditLabel() {
   int fontSize = 12;
   setFont( new java.awt.Font( "SansSerif", java.awt.Font.BOLD, (int)fontSize) );
   setForeground( java.awt.Color.black );
   setText( "drop here" );
   setOpaque( false );
   this.setDropTarget( new java.awt.dnd.DropTarget( this, this ) );
   }

  // DropTargetListener interface
  protected void checkDrag (java.awt.dnd.DropTargetDragEvent dtde) {
   //TODO: feedback
   //TODO: better detection
   if (AuthoringToolResources.safeIsDataFlavorSupported(dtde, ElementReferenceTransferable.elementReferenceFlavor )) {
    dtde.acceptDrag( java.awt.dnd.DnDConstants.ACTION_MOVE );
   } else if (AuthoringToolResources.safeIsDataFlavorSupported(dtde, ResponsePrototypeReferenceTransferable.responsePrototypeReferenceFlavor )) {
    dtde.acceptDrag( java.awt.dnd.DnDConstants.ACTION_MOVE );
   } else {
    dtde.rejectDrag();
    }
   }

  public void dragEnter (java.awt.dnd.DropTargetDragEvent dtde) {
   checkDrag( dtde );
   }

  public void dragOver (java.awt.dnd.DropTargetDragEvent dtde) {
   checkDrag( dtde );
   }

  public void dropActionChanged (java.awt.dnd.DropTargetDragEvent dtde) {
   checkDrag( dtde );
   }

  public void dragExit (java.awt.dnd.DropTargetEvent dte) {
   //TODO: feedback
   }

  public void drop (java.awt.dnd.DropTargetDropEvent dtde) {
   java.awt.datatransfer.Transferable transferable = dtde.getTransferable();

   try {
    if (AuthoringToolResources.safeIsDataFlavorSupported(transferable, ElementReferenceTransferable.elementReferenceFlavor )) {
     dtde.acceptDrop( java.awt.dnd.DnDConstants.ACTION_MOVE );
     edu.cmu.cs.stage3.alice.core.Element element = (edu.cmu.cs.stage3.alice.core.Element)transferable.getTransferData( ElementReferenceTransferable.elementReferenceFlavor );
     EditorComponent.this.editElement( element );
     dtde.dropComplete( true );
    } else if (AuthoringToolResources.safeIsDataFlavorSupported(transferable, CallToUserDefinedResponsePrototypeReferenceTransferable.callToUserDefinedResponsePrototypeReferenceFlavor )) {
     dtde.acceptDrop( java.awt.dnd.DnDConstants.ACTION_MOVE );
     edu.cmu.cs.stage3.alice.authoringtool.util.CallToUserDefinedResponsePrototype callToUserDefinedResponsePrototype = (edu.cmu.cs.stage3.alice.authoringtool.util.CallToUserDefinedResponsePrototype)transferable.getTransferData( CallToUserDefinedResponsePrototypeReferenceTransferable.callToUserDefinedResponsePrototypeReferenceFlavor );
     EditorComponent.this.editElement( callToUserDefinedResponsePrototype.getActualResponse() );
     dtde.dropComplete( true );
    } else if (AuthoringToolResources.safeIsDataFlavorSupported(transferable, CallToUserDefinedQuestionPrototypeReferenceTransferable.callToUserDefinedQuestionPrototypeReferenceFlavor )) {
     dtde.acceptDrop( java.awt.dnd.DnDConstants.ACTION_MOVE );
     edu.cmu.cs.stage3.alice.authoringtool.util.CallToUserDefinedQuestionPrototype callToUserDefinedQuestionPrototype = (edu.cmu.cs.stage3.alice.authoringtool.util.CallToUserDefinedQuestionPrototype)transferable.getTransferData( CallToUserDefinedQuestionPrototypeReferenceTransferable.callToUserDefinedQuestionPrototypeReferenceFlavor );
     EditorComponent.this.editElement( callToUserDefinedQuestionPrototype.getActualQuestion() );
     dtde.dropComplete( true );
    } else {
     dtde.rejectDrop();
     dtde.dropComplete( false );
     }
   } catch( java.awt.datatransfer.UnsupportedFlavorException e) {
    AuthoringTool.getInstance().showErrorDialog( "Drop didn't work: bad flavor", e );
    dtde.dropComplete( false );
   } catch( java.io.IOException e) {
    AuthoringTool.getInstance().showErrorDialog( "Drop didn't work: IOException", e );
    dtde.dropComplete( false );
   } catch( Throwable t) {
    AuthoringTool.getInstance().showErrorDialog( "Drop didn't work.", t );
    dtde.dropComplete( false );
    }
   }
  }

 // class HighlightButton
 class HighlightButton extends javax.swing.JButton {
  protected javax.swing.border.Border highlightBorder = new HighlightBorder( true );
  protected javax.swing.border.Border pressedBorder = new HighlightBorder( false );
  protected java.awt.Insets insets = new java.awt.Insets( 4, 4, 4, 4 );

  public HighlightButton () {
   this.setHorizontalTextPosition( javax.swing.SwingConstants.CENTER );
   this.setVerticalTextPosition( javax.swing.SwingConstants.BOTTOM );
   this.setOpaque( false );
   this.setFocusPainted( false );
   this.setContentAreaFilled( false );
   this.setRolloverEnabled( true );
   this.setBorder( null );

   this.getModel().addChangeListener(
     new javax.swing.event.ChangeListener() {
      public void stateChanged( javax.swing.event.ChangeEvent ev) {
       HighlightButton.this.updateBorder();
       }
      }
    );
   }

  //Rem @Override
  public java.awt.Insets getInsets () {
   return insets;
   }

  protected void updateBorder () {
   if (getModel().isEnabled()) {
    if (getModel().isPressed()) {
     if (getModel().isArmed()) {
      setBorder( pressedBorder );
     } else {
      setBorder( highlightBorder );
      }
    } else if ( getModel().isRollover()) {
     setBorder( highlightBorder );
    } else {
     setBorder( null );
     }
   } else {
    setBorder( null );
    }
   }

  class HighlightBorder extends javax.swing.border.AbstractBorder {
   protected java.awt.Color highlightColor = java.awt.Color.white;
   protected java.awt.Color shadowColor = java.awt.Color.gray;
   protected boolean raised;

   public HighlightBorder (boolean isRaised) {
    this.raised = isRaised;
    }

   public void setRaised (boolean isRaised) {
    this.raised = isRaised;
    }

   public boolean isRaised () {
    return raised;
    }

   //Rem @Override
   public void paintBorder (java.awt.Component c, java.awt.Graphics g, int x, int y, int width, int height) {
    java.awt.Color oldColor = g.getColor();
    if (raised) {
     g.setColor( highlightColor );
     g.drawLine( x, y, x + width - 1, y );
     g.drawLine( x, y, x, y + height - 1 );
     g.setColor( shadowColor );
     g.drawLine( x + 1, y + height - 1, x + width - 1, y + height - 1 );
     g.drawLine( x + width - 1, y + 1, x + width - 1, y + height - 1 );
    } else {
     g.setColor( shadowColor );
     g.drawLine( x, y, x + width - 2, y );
     g.drawLine( x, y, x, y + height - 2 );
     g.setColor( highlightColor );
     g.drawLine( x, y + height - 1, x + width - 1, y + height - 1 );
     g.drawLine( x + width - 1, y, x + width - 1, y + height - 1 );
     }
    g.setColor( oldColor );
    }

   //Rem @Override
   public java.awt.Insets getBorderInsets (java.awt.Component c) {
    return new java.awt.Insets( 1, 1, 1, 1 );
    }

   //Rem @Override
   public java.awt.Insets getBorderInsets (java.awt.Component c, java.awt.Insets insets) {
    insets.left = insets.top = insets.right = insets.bottom = 1;
    return insets;
    }

   //Rem @Override
   public boolean isBorderOpaque () {
    return true;
    }

   } // class HighlightBorder extends javax.swing.border.AbstractBorder

  } // class HighlightButton
   

 }
